import backtrader as bt

class BollingerBandsStrategy(bt.Strategy):
    """
    一个基于布林带的均值回归策略。
    当价格触及或跌破布林带下轨时，买入。
    当价格触及或升破布林带上轨时，卖出。
    """
    params = (
        ('period', 20),
        ('devfactor', 2.0), # 标准差倍数
        ('printlog', True),
    )

    def __init__(self):
        self.order = None
        # 添加布林带指标
        self.bband = bt.indicators.BollingerBands(
            period=self.p.period, devfactor=self.p.devfactor
        )

    def log(self, txt, dt=None, doprint=False):
        if self.params.printlog or doprint:
            dt = dt or self.datas[0].datetime.date(0)
            print(f'{dt.isoformat()}, {txt}')

    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            return
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(f'BUY EXECUTED, Price: {order.executed.price:.2f}')
            else:
                self.log(f'SELL EXECUTED, Price: {order.executed.price:.2f}')
        self.order = None

    def next(self):
        if self.order:
            return

        if not self.position:
            # 如果收盘价低于布林带下轨
            if self.data.close < self.bband.lines.bot:
                self.log(f'BUY CREATE, Close: {self.data.close[0]:.2f}, BBot: {self.bband.lines.bot[0]:.2f}')
                self.order = self.buy()
        else:
            # 如果收盘价高于布林带上轨
            if self.data.close > self.bband.lines.top:
                self.log(f'SELL CREATE, Close: {self.data.close[0]:.2f}, BTop: {self.bband.lines.top[0]:.2f}')
                self.order = self.sell() 